package com.ruoyi.framework.shiro.service;

import java.security.SecureRandom;
import java.util.Date;
import java.util.List;
import java.util.Set;

import org.apache.shiro.crypto.hash.Md5Hash;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import com.ruoyi.common.constant.Constants;
import com.ruoyi.common.constant.ShiroConstants;
import com.ruoyi.common.constant.UserConstants;
import com.ruoyi.common.core.domain.entity.SysRole;
import com.ruoyi.common.core.domain.entity.SysUser;
import com.ruoyi.common.enums.UserStatus;
import com.ruoyi.common.exception.user.BlackListException;
import com.ruoyi.common.exception.user.CaptchaException;
import com.ruoyi.common.exception.user.UserBlockedException;
import com.ruoyi.common.exception.user.UserDeleteException;
import com.ruoyi.common.exception.user.UserNotExistsException;
import com.ruoyi.common.exception.user.UserPasswordNotMatchException;
import com.ruoyi.common.utils.DateUtils;
import com.ruoyi.common.utils.IpUtils;
import com.ruoyi.common.utils.MessageUtils;
import com.ruoyi.common.utils.ServletUtils;
import com.ruoyi.common.utils.ShiroUtils;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.framework.manager.AsyncManager;
import com.ruoyi.framework.manager.factory.AsyncFactory;
import com.ruoyi.system.service.ISysConfigService;
import com.ruoyi.system.service.ISysMenuService;
import com.ruoyi.system.service.ISysUserService;

/**
 * 系统登录服务类
 * 负责处理用户登录验证、令牌生成、登录状态管理等核心登录相关
 *
 * @author ruoyi
 */
@Component
public class SysLoginService {
    @Autowired
    private SysPasswordService passwordService;

    @Autowired
    private ISysUserService userService;

    @Autowired
    private ISysMenuService menuService;

    @Autowired
    private ISysConfigService configService;

    /**
     * 注册微信用户
     *
     * @param username 用户名(登录账号)
     * @param password 密码(用户自定义密码）
     * @return 注册成功的用户信息
     */
    public SysUser registerUser(String username, String password) {
        // 检查用户名是否已存在
        SysUser existingUser = userService.selectUserByLoginName(username);
        if (existingUser != null) {
            return null; // 用户名已存在，返回null
        }

        // 生成12位随机密码
//        String password = generateRandomString(12);
        // 生成6位随机盐值
        String salt = generateRandomString(6);
        // 对密码进行MD5加密
        String encryptedPassword = new Md5Hash(username + password + salt).toHex();

        // 创建新用户对象
        SysUser user = new SysUser();
        user.setLoginName(username);                    // 设置登录名（用户名）
        user.setPassword(encryptedPassword);            // 设置加密后的密码
        user.setSalt(salt);                             // 设置盐值
        user.setDeptId(100L);                           // 设置部门ID为100
        user.setUserName("微信用户");                    // 设置用户名称
        user.setUserType("01");                        // 设置用户类型为"01"
        user.setLoginDate(new Date());                  // 设置登录时间为当前时间
        user.setEmail("wechat@qq.com");                 // 设置邮箱
        user.setStatus(UserConstants.NORMAL);           // 设置账号状态为正常
        user.setDelFlag(UserConstants.UN_DELETED);      // 设置未删除
        user.setCreateBy("admin");                      // 设置创建者为系统
        user.setCreateTime(new Date());                 // 设置创建时间
        user.setRemark("微信用户:微信小程序端自动创建的用户"); // 设置备注

        // 调用用户服务插入用户
        userService.insertUser(user);

        // 为用户分配默认角色（角色ID为2）
        Long[] roleIds = {2L};
        userService.insertUserAuth(user.getUserId(), roleIds);
        return user;
    }

    /**
     * 生成指定长度的随机密码
     *
     * @param length 密码长度
     * @return 随机密码
     */
    private String generateRandomString(int length) {
        // 待生成字符串的字符集，排除容易混淆的字符
        String chars = "ABCDEFGHJKLMNPQRSTUVWXYZabcdefghjkmnpqrstuvwxyz23456789!@#$%^&*";
        SecureRandom random = new SecureRandom();
        StringBuilder sb = new StringBuilder(length);
        for (int i = 0; i < length; i++) {
            sb.append(chars.charAt(random.nextInt(chars.length())));
        }
        return sb.toString();
    }

    /**
     * 用户登录方法，验证用户名和密码并返回用户信息
     *
     * @param username 登录用户名
     * @param password 登录密码
     * @return 登录成功的用户信息对象（SysUser），验证失败时可能返回null或抛出异常
     */
    public SysUser login(String username, String password, String isAPI) {
        // 获取当前请求中的验证码
        String currentCaptcha = (String) ServletUtils.getRequest().getAttribute(ShiroConstants.CURRENT_CAPTCHA);
        // 验证码校验
        if (ShiroConstants.CAPTCHA_ERROR.equals(currentCaptcha)) {
            AsyncManager.me().execute(AsyncFactory.recordLogininfo(username, Constants.LOGIN_FAIL, MessageUtils.message("user.jcaptcha.error")));
            throw new CaptchaException();
        }
        // 用户名或密码为空 错误
        if (StringUtils.isEmpty(username) || StringUtils.isEmpty(password)) {
            AsyncManager.me().execute(AsyncFactory.recordLogininfo(username, Constants.LOGIN_FAIL, MessageUtils.message("not.null")));
            throw new UserNotExistsException();
        }
        // 密码如果不在指定范围内 错误
        if (password.length() < UserConstants.PASSWORD_MIN_LENGTH || password.length() > UserConstants.PASSWORD_MAX_LENGTH) {
            AsyncManager.me().execute(AsyncFactory.recordLogininfo(username, Constants.LOGIN_FAIL, MessageUtils.message("user.password.not.match")));
            throw new UserPasswordNotMatchException();
        }

        // 用户名不在指定范围内 错误
        if (username.length() < UserConstants.USERNAME_MIN_LENGTH || username.length() > UserConstants.USERNAME_MAX_LENGTH) {
            AsyncManager.me().execute(AsyncFactory.recordLogininfo(username, Constants.LOGIN_FAIL, MessageUtils.message("user.password.not.match")));
            throw new UserPasswordNotMatchException();
        }

        // IP黑名单校验
        String blackStr = configService.selectConfigByKey("sys.login.blackIPList");
        if (IpUtils.isMatchedIp(blackStr, ShiroUtils.getIp())) {
            AsyncManager.me().execute(AsyncFactory.recordLogininfo(username, Constants.LOGIN_FAIL, MessageUtils.message("login.blocked")));
            throw new BlackListException();
        }

        // 查询用户信息
        SysUser user = userService.selectUserByLoginName(username);

        /**
         if (user == null && maybeMobilePhoneNumber(username))
         {
         user = userService.selectUserByPhoneNumber(username);
         }

         if (user == null && maybeEmail(username))
         {
         user = userService.selectUserByEmail(username);
         }
         */

        if (user == null) {
            if (ShiroConstants.IS_API.equals(isAPI)) {
                // API请求，注册用户
                user = registerUser(username, password);
            } else {
                // 不是API请求，抛出用户不存在异常
                AsyncManager.me().execute(AsyncFactory.recordLogininfo(username, Constants.LOGIN_FAIL, MessageUtils.message("user.not.exists")));
                throw new UserNotExistsException();
            }
        }

        if (UserStatus.DELETED.getCode().equals(user.getDelFlag())) {
            AsyncManager.me().execute(AsyncFactory.recordLogininfo(username, Constants.LOGIN_FAIL, MessageUtils.message("user.password.delete")));
            throw new UserDeleteException();
        }

        if (UserStatus.DISABLE.getCode().equals(user.getStatus())) {
            AsyncManager.me().execute(AsyncFactory.recordLogininfo(username, Constants.LOGIN_FAIL, MessageUtils.message("user.blocked")));
            throw new UserBlockedException();
        }

        passwordService.validate(user, password);

        AsyncManager.me().execute(AsyncFactory.recordLogininfo(username, Constants.LOGIN_SUCCESS, MessageUtils.message("user.login.success")));
        setRolePermission(user);
        recordLoginInfo(user.getUserId());
        return user;
    }

    /**
     private boolean maybeEmail(String username)
     {
     if (!username.matches(UserConstants.EMAIL_PATTERN))
     {
     return false;
     }
     return true;
     }

     private boolean maybeMobilePhoneNumber(String username)
     {
     if (!username.matches(UserConstants.MOBILE_PHONE_NUMBER_PATTERN))
     {
     return false;
     }
     return true;
     }
     */

    /**
     * 设置角色权限
     *
     * @param user 用户信息
     */
    public void setRolePermission(SysUser user) {
        List<SysRole> roles = user.getRoles();
        if (roles != null && !roles.isEmpty()) {
            // 设置permissions属性，以便数据权限匹配权限
            for (SysRole role : roles) {
                if (StringUtils.equals(role.getStatus(), UserConstants.ROLE_NORMAL) && !role.isAdmin()) {
                    Set<String> rolePerms = menuService.selectPermsByRoleId(role.getRoleId());
                    role.setPermissions(rolePerms);
                }
            }
        }
    }

    /**
     * 记录登录信息
     *
     * @param userId 用户ID
     */
    public void recordLoginInfo(Long userId) {
        userService.updateLoginInfo(userId, ShiroUtils.getIp(), DateUtils.getNowDate());
    }
}
